﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AppFx.Console
{
    /// <summary>
    /// A class simplifying console-applications.
    /// </summary>
    public class BaseConsole
    {
        #region Properties

        /// <summary>
        /// Cancels the running loop.
        /// </summary>
        public bool Cancel { get; set; }

        /// <summary>
        /// Gets or sets the WelcomeText to display.
        /// </summary>
        public string WelcomeText { get; set; }

        /// <summary>
        /// Title of the console-application.
        /// </summary>
        public string Title
        {
            get { return System.Console.Title; }
            set { System.Console.Title = value; }
        }

        /// <summary>
        /// Gets or Sets the allowed commands.
        /// </summary>
        public List<ConsoleCommand> Commands { get; set; }

        #endregion

        #region Constructors

        /// <summary>
        /// Creates a new BaseConsole settings it's title.
        /// </summary>
        /// <param name="title">Title to display.</param>
        public BaseConsole(string title, string welcomeText, string helpText)
        {
            Title = title;
            WelcomeText = welcomeText;
            Commands = new List<ConsoleCommand>();

            ConsoleCommand commandsCommand = new ConsoleCommand("commands", new ExecuteDelegate(delegate(ConsoleCommand c)
            {
                PrintCommands();
            }), null);

            ConsoleCommand helpCommand = new ConsoleCommand("help", new ExecuteDelegate(delegate(ConsoleCommand c)
                {
                    System.Console.WriteLine();
                    System.Console.WriteLine(helpText);
                    System.Console.WriteLine();
                }), new string[]{"", "?"});

            ConsoleCommand exitCommand = new ConsoleCommand("exit", new ExecuteDelegate(delegate(ConsoleCommand c)
                {
                    Cancel = true;
                }), null);

            Commands.Add(commandsCommand);
            Commands.Add(helpCommand);
            Commands.Add(exitCommand);
        }

        #endregion

        #region Methods

        /// <summary>
        /// Loops the console-application.
        /// </summary>
        public void Loop()
        {
            System.Console.WriteLine(WelcomeText);

            while (!Cancel)
            {
                ConsoleCommand command = null;
                string input = System.Console.ReadLine();
                var nameCommands = Commands.Where(c => c.Name == input);

                if (nameCommands != null && nameCommands.Count() > 0)
                {
                    command = nameCommands.First();
                }
                else
                {
                    foreach (var cmd in Commands)
                    {
                        var aliasCommands = cmd.Aliases.Where(a => a == input);
                        if (aliasCommands != null && aliasCommands.Count() > 0)
                        {
                            command = cmd;
                        }
                    }
                }
                if (command == null)
                {
                    System.Console.WriteLine("The given input does not match any command or alias.");
                    System.Console.WriteLine("Please use one of the following commands:");
                    PrintCommands();
                }
                else
                    command.Execute();
            }
        }

        /// <summary>
        /// Prints all available commands to the screen.
        /// </summary>
        public void PrintCommands()
        {
            foreach (var cmd in Commands)
            {
                System.Console.WriteLine("-> {0}", cmd.Name);
                foreach (var alias in cmd.Aliases)
                    System.Console.WriteLine("  -> {0} (alias)", alias);
            }
        }

        #endregion
    }
}
